﻿/*
 Wrap Interface of Kinect2
 According to MS Kinect SDK Vesrion 2.0.1410.19000

 Date : 2014/12/3
 Version : 0.5
 
The MIT License (MIT)

Copyright (c) 2014 DavidWTF

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices.ComTypes;

namespace Kinect2
{
    namespace Fusion
    {
        using HRESULT = System.Int32;

        public class KinectFusion
        {
            [DllImportAttribute("Kinect20.Fusion")]
            public static extern HRESULT NuiFusionGetDeviceInfo(
                [In] NUI_FUSION_RECONSTRUCTION_PROCESSOR_TYPE type,
                [In] int index,
                [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] char[] description,
                [In] uint descriptionSizeInChars,
                [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 5)] char[] instancePath,
                [In] uint instancePathSizeInChars,
                [Out] out uint memoryKB);

            [DllImportAttribute("Kinect20.Fusion")]
            public static extern HRESULT NuiFusionCreateReconstruction(
                [In] ref NUI_FUSION_RECONSTRUCTION_PARAMETERS reconstructionParameters,
                [In] NUI_FUSION_RECONSTRUCTION_PROCESSOR_TYPE reconstructionProcessorType,
                [In] int deviceIndex,
                [In] ref Matrix4 initialWorldToCameraTransform,
                [Out, MarshalAs(UnmanagedType.Interface)] out INuiFusionReconstruction nuiFusionReconstruction);

            [DllImportAttribute("Kinect20.Fusion")]
            public static extern HRESULT NuiFusionCreateColorReconstruction(
                [In] ref NUI_FUSION_RECONSTRUCTION_PARAMETERS reconstructionParameters,
                [In] NUI_FUSION_RECONSTRUCTION_PROCESSOR_TYPE reconstructionProcessorType,
                [In] int deviceIndex,
                [In] ref Matrix4 initialWorldToCameraTransform,
                [Out, MarshalAs(UnmanagedType.Interface)] out INuiFusionColorReconstruction nuiFusionColorReconstruction);

            [DllImportAttribute("Kinect20.Fusion")]
            public static extern HRESULT NuiFusionCreateImageFrame(
                [In] NUI_FUSION_IMAGE_TYPE frameType,
                [In] uint width,
                [In] uint height,
                [In] ref  NUI_FUSION_CAMERA_PARAMETERS cameraParameters,
                [Out, MarshalAs(UnmanagedType.LPArray, SizeConst = 1)] out NUI_FUSION_IMAGE_FRAME[] imageFrame);

            [DllImportAttribute("Kinect20.Fusion")]
            public static extern HRESULT NuiFusionReleaseImageFrame(
                [In] ref NUI_FUSION_IMAGE_FRAME imageFrame);

            [DllImportAttribute("Kinect20.Fusion")]
            public static extern HRESULT NuiFusionDepthToDepthFloatFrame(
                [In, MarshalAs(UnmanagedType.LPArray)] UInt16[] depthImageData,
                [In] uint depthImageDataWidth,
                [In] uint depthImageDataHeight,
                [In] ref NUI_FUSION_IMAGE_FRAME depthFloatFrame,
                [In] float minDepthClip,
                [In] float maxDepthClip,
                [In] bool mirrorDepth);

            [DllImportAttribute("Kinect20.Fusion")]
            public static extern HRESULT NuiFusionDepthFloatFrameToPointCloud(
                [In] ref NUI_FUSION_IMAGE_FRAME depthFloatFrame,
                [In] ref NUI_FUSION_IMAGE_FRAME pointCloudFrame);

            [DllImportAttribute("Kinect20.Fusion")]
            public static extern HRESULT NuiFusionShadePointCloud(
                [In] ref NUI_FUSION_IMAGE_FRAME pointCloudFrame,
                [In] ref Matrix4 worldToCameraTransform,
                [In] ref Matrix4 worldToBGRTransform,
                [In] ref NUI_FUSION_IMAGE_FRAME shadedSurfaceFrame,
                [In] ref NUI_FUSION_IMAGE_FRAME shadedSurfaceNormalsFrame);

            [DllImportAttribute("Kinect20.Fusion")]
            public static extern HRESULT NuiFusionAlignPointClouds(
                [In] ref NUI_FUSION_IMAGE_FRAME referencePointCloudFrame,
                [In] ref NUI_FUSION_IMAGE_FRAME observedPointCloudFrame,
                [In] ushort maxAlignIterationCount,
                [In] ref NUI_FUSION_IMAGE_FRAME deltaFromReferenceFrame,
                [Out] out Matrix4 referenceToObservedTransform
            );

            [DllImportAttribute("Kinect20.Fusion")]
            public static extern HRESULT NuiFusionCreateCameraPoseFinder(
                [In] ref NUI_FUSION_CAMERA_POSE_FINDER_PARAMETERS cameraPoseFinderParameters,
                [In] IntPtr /*ref uint*/ randomFeatureLocationAndThresholdSeed,
                [Out, MarshalAs(UnmanagedType.Interface)] out INuiFusionCameraPoseFinder nuiFusionCameraPoseFinder);
        }

        [StructLayoutAttribute(LayoutKind.Sequential, Pack = 8)]
        public struct Matrix4
        {
            [MarshalAs(UnmanagedType.LPStruct, SizeConst = 16)]
            float[] _m;
            public float M11
            {
                get { return _m[0]; }
                set { _m[0] = value; }
            }
            public float M12
            {
                get { return _m[1]; }
                set { _m[1] = value; }
            }
            public float M13
            {
                get { return _m[2]; }
                set { _m[2] = value; }
            }
            public float M14
            {
                get { return _m[3]; }
                set { _m[3] = value; }
            }
            public float M21
            {
                get { return _m[4]; }
                set { _m[4] = value; }
            }
            public float M22
            {
                get { return _m[5]; }
                set { _m[5] = value; }
            }
            public float M23
            {
                get { return _m[6]; }
                set { _m[6] = value; }
            }
            public float M24
            {
                get { return _m[7]; }
                set { _m[7] = value; }
            }
            public float M31
            {
                get { return _m[8]; }
                set { _m[8] = value; }
            }
            public float M32
            {
                get { return _m[9]; }
                set { _m[9] = value; }
            }
            public float M33
            {
                get { return _m[10]; }
                set { _m[10] = value; }
            }
            public float M34
            {
                get { return _m[11]; }
                set { _m[11] = value; }
            }
            public float M41
            {
                get { return _m[12]; }
                set { _m[12] = value; }
            }
            public float M42
            {
                get { return _m[13]; }
                set { _m[13] = value; }
            }
            public float M43
            {
                get { return _m[14]; }
                set { _m[14] = value; }
            }
            public float M44
            {
                get { return _m[15]; }
                set { _m[15] = value; }
            }
            Matrix4(bool identy)
            {
                _m = new float[16];
                for (int i = 0; i < 16; i++)
                    _m[i] = 0;
                if (identy)
                {
                    _m[0] = 1.0f;
                    _m[5] = 1.0f;
                    _m[10] = 1.0f;
                    _m[15] = 1.0f;
                }

            }
            static Matrix4 _identity = new Matrix4(true);
            public static Matrix4 Identity { get { return _identity; } }
            public static bool operator !=(Matrix4 mat1, Matrix4 mat2)
            {
                return !(mat1 == mat2);
            }
            public static bool operator ==(Matrix4 mat1, Matrix4 mat2)
            {
                if (object.ReferenceEquals(mat1, mat2))
                    return true;

                if (((object)mat1 == null) || ((object)mat2 == null))
                    return false;

                for (int i = 0; i < 16; i++)
                    if (mat1._m[i] != mat2._m[i])
                        return false;
                return true;
            }
            public bool Equals(Matrix4 mat)
            {
                if ((object)mat == null)
                    return false;

                for (int i = 0; i < 16; i++)
                    if (_m[i] != mat._m[i])
                        return false;
                return true;
            }
            public override bool Equals(object obj)
            {
                if (obj == null)
                    return false;

                if (obj.GetType() == typeof(Matrix4))
                    return this == (Matrix4)obj;

                return false;
            }
            public override int GetHashCode()
            {
                return base.GetHashCode();
            }
        };

        [StructLayoutAttribute(LayoutKind.Sequential, Pack = 8)]
        public struct NUI_FUSION_BUFFER
        {
            public uint Pitch;
            public IntPtr pBits;
        };

        [StructLayoutAttribute(LayoutKind.Sequential)]
        public struct Vector3
        {
            public float x;
            public float y;
            public float z;
            public float X
            {
                get { return x; }
                set { x = value; }
            }
            public float Y
            {
                get { return y; }
                set { y = value; }
            }
            public float Z
            {
                get { return z; }
                set { z = value; }
            }
            public static bool operator !=(Vector3 vector1, Vector3 vector2)
            {
                return !(vector1 == vector2);
            }
            public static bool operator ==(Vector3 vector1, Vector3 vector2)
            {
                if (object.ReferenceEquals(vector1, vector2))
                    return true;

                if (((object)vector1 == null) || ((object)vector2 == null))
                    return false;

                if (vector1.x != vector2.x || vector1.y != vector2.y || vector1.z != vector2.z)
                    return false;
                return true;
            }
            public bool Equals(Vector3 other)
            {
                if ((object)other == null)
                    return false;

                return x == other.x && y == other.y && z == other.z;
            }
            public override bool Equals(object obj)
            {
                if (obj == null)
                    return false;

                if (obj.GetType() == typeof(Vector3))
                    return this == (Vector3)obj;

                return false;
            }
            public override int GetHashCode()
            {
                return base.GetHashCode();
            }
        };

        [StructLayoutAttribute(LayoutKind.Sequential)]
        public struct NUI_FUSION_CAMERA_PARAMETERS
        {
            public float focalLengthX;
            public float focalLengthY;
            public float principalPointX;
            public float principalPointY;
        };

        public enum FusionImageType
        {
            Invalid = 0,
            Color = 1,
            Float = 2,
            PointCloud = 3
        };

        public enum NUI_FUSION_IMAGE_TYPE
        {
            INVALID = 0,
            COLOR = 1,
            FLOAT = 2,
            POINT_CLOUD = 3
        };

        [StructLayoutAttribute(LayoutKind.Sequential)]
        public struct NUI_FUSION_RECONSTRUCTION_PARAMETERS
        {
            public float voxelsPerMeter;
            public uint voxelCountX;
            public uint voxelCountY;
            public uint voxelCountZ;
        };

        public enum ReconstructionProcessor
        {
            Cpu = 1,
            Amp = 2
        }

        public enum NUI_FUSION_RECONSTRUCTION_PROCESSOR_TYPE
        {
            CPU = 1,
            AMP = 2
        };

        [StructLayoutAttribute(LayoutKind.Sequential)]
        public struct NUI_FUSION_IMAGE_FRAME
        {
            public uint width;
            public uint height;
            public NUI_FUSION_IMAGE_TYPE imageType;
            [MarshalAs(UnmanagedType.LPStruct)]
            public NUI_FUSION_CAMERA_PARAMETERS cameraParameters;
            [MarshalAs(UnmanagedType.LPStruct)]
            public NUI_FUSION_BUFFER frameBuffer;
        };

        [Guid("43102C25-82EE-4958-AA24-AC5456BF83C0")]
        [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
        [ComImport()]
        public interface INuiFusionMesh
        {
            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            [PreserveSig]
            uint VertexCount();

            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            void GetVertices(
                [Out] out IntPtr /*Vector3*/ vertices);

            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            [PreserveSig]
            uint NormalCount();

            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            void GetNormals(
                [Out] out IntPtr /*Vector3[]*/ normals);

            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            [PreserveSig]
            uint TriangleVertexIndexCount();

            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            void GetTriangleIndices(
                [Out] out IntPtr /*int[]*/ triangleVertexIndices);

        };

        [Guid("AC19AD5F-2218-4C08-A00F-C981C50A09DF")]
        [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
        [ComImport()]
        public interface INuiFusionReconstruction
        {
            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            void ResetReconstruction(
                [In] ref Matrix4 initialWorldToCameraTransform,
                [In] IntPtr /*ref Matrix4*/ worldToVolumeTransform);

            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            void AlignDepthFloatToReconstruction(
                [In] ref NUI_FUSION_IMAGE_FRAME depthFloatFrame,
                [In] ushort maxAlignIterationCount,
                [In] ref NUI_FUSION_IMAGE_FRAME deltaFromReferenceFrame,
                [Out] out float alignmentEnergy,
                [In] ref Matrix4 worldToCameraTransform);

            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            void GetCurrentWorldToCameraTransform(
                [Out] out Matrix4 worldToCameraTransform);

            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            void GetCurrentWorldToVolumeTransform(
                [Out] out Matrix4 worldToVolumeTransform);

            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            void IntegrateFrame(
                [In] ref NUI_FUSION_IMAGE_FRAME depthFloatFrame,
                [In] ushort maxIntegrationWeight,
                [In] ref Matrix4 worldToCameraTransform);

            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            void ProcessFrame(
                [In] ref NUI_FUSION_IMAGE_FRAME depthFloatFrame,
                [In] ushort maxAlignIterationCount,
                [In] ushort maxIntegrationWeight,
                [Out] out float alignmentEnergy,
                [In] ref Matrix4 worldToCameraTransform);

            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            void CalculatePointCloud(
                [In] ref NUI_FUSION_IMAGE_FRAME pointCloudFrame,
                [In] ref Matrix4 worldToCameraTransform);

            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            void CalculateMesh(
                [In] uint voxelStep,
                [Out, MarshalAs(UnmanagedType.Interface)] out INuiFusionMesh mesh);

            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            void ExportVolumeBlock(
                [In] uint sourceOriginX,
                [In] uint sourceOriginY,
                [In] uint sourceOriginZ,
                [In] uint destinationResolutionX,
                [In] uint destinationResolutionY,
                [In] uint destinationResolutionZ,
                [In] uint voxelStep,
                [In] uint cbVolumeBlock,
                [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 7)] short[] volumeBlock);

            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            void ImportVolumeBlock(
                [In] uint cbVolumeBlock,
                [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] short[] volumeBlock);

            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            void DepthToDepthFloatFrame(
                [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] UInt16[] depthImageData,
                [In] uint countDepthImageDataBytes,
                [In] ref NUI_FUSION_IMAGE_FRAME depthFloatFrame,
                [In] float minDepthClip,
                [In] float maxDepthClip,
                [In] bool mirrorDepth);

            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            void SmoothDepthFloatFrame(
                [In] ref NUI_FUSION_IMAGE_FRAME depthFloatFrame,
                [In] ref NUI_FUSION_IMAGE_FRAME smoothDepthFloatFrame,
                [In] uint kernelWidth,
                [In] float distanceThreshold);

            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            void AlignPointClouds(
                [In] ref NUI_FUSION_IMAGE_FRAME referencePointCloudFrame,
                [In] ref NUI_FUSION_IMAGE_FRAME observedPointCloudFrame,
                [In] ushort maxAlignIterationCount,
                [In] ref NUI_FUSION_IMAGE_FRAME deltaFromReferenceFrame,
                [Out] out float alignmentEnergy,
                [In, Out] ref Matrix4 referenceToObservedTransform);

            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            void SetAlignDepthFloatToReconstructionReferenceFrame(
                [In] ref NUI_FUSION_IMAGE_FRAME referenceDepthFloatFrame);

            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            void CalculatePointCloudAndDepth(
                [In] ref NUI_FUSION_IMAGE_FRAME pointCloudFrame,
                [In] ref NUI_FUSION_IMAGE_FRAME depthFloatFrame,
                [In] ref Matrix4 worldToCameraTransform);

        };

        [Guid("461C71E1-2017-4322-AEA3-303BB8DC545C")]
        [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
        [ComImport()]
        public interface INuiFusionColorMesh
        {
            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            [PreserveSig]
            uint VertexCount();

            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            void GetVertices(
                [Out] out IntPtr /*Vector3[]*/ vertices);

            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            [PreserveSig]
            uint NormalCount();

            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            void GetNormals(
                [Out] out IntPtr /*Vector3[]*/ normals);

            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            [PreserveSig]
            uint TriangleVertexIndexCount();

            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            void GetTriangleIndices(
                [Out] out IntPtr /*int[]*/ triangleVertexIndices);

            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            [PreserveSig]
            uint ColorCount();

            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            void GetColors(
                 [Out] out IntPtr /*int[]*/ colors);

        };

        [Guid("A833A9A1-3608-49FA-982A-E050BFFD8C96")]
        [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
        [ComImport()]
        public interface INuiFusionColorReconstruction
        {
            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            void ResetReconstruction(
                [In] ref Matrix4 initialWorldToCameraTransform,
                [In] IntPtr /*ref Matrix4*/ worldToVolumeTransform);

            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            void AlignDepthFloatToReconstruction(
                [In] ref NUI_FUSION_IMAGE_FRAME depthFloatFrame,
                [In] ushort maxAlignIterationCount,
                [In] ref NUI_FUSION_IMAGE_FRAME deltaFromReferenceFrame,
                [Out] out float alignmentEnergy,
                [In] ref Matrix4 worldToCameraTransform);

            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            void GetCurrentWorldToCameraTransform(
                [Out] out Matrix4 worldToCameraTransform);

            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            void GetCurrentWorldToVolumeTransform(
                [Out] out Matrix4 worldToVolumeTransform);

            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            void IntegrateFrame(
                [In] ref NUI_FUSION_IMAGE_FRAME depthFloatFrame,
                [In] IntPtr /*ref NUI_FUSION_IMAGE_FRAME*/ colorFrame,
                [In] ushort maxIntegrationWeight,
                [In] float maxColorIntegrationAngle,
                [In] ref Matrix4 worldToCameraTransform);

            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            void ProcessFrame(
                [In] ref NUI_FUSION_IMAGE_FRAME depthFloatFrame,
                [In] IntPtr /*ref NUI_FUSION_IMAGE_FRAME*/ colorFrame,
                [In] ushort maxAlignIterationCount,
                [In] ushort maxIntegrationWeight,
                [In] float maxColorIntegrationAngle,
                [Out] out float alignmentEnergy,
                [In] ref Matrix4 worldToCameraTransform);

            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            void CalculatePointCloud(
                [In] ref NUI_FUSION_IMAGE_FRAME pointCloudFrame,
                [In] IntPtr /*ref NUI_FUSION_IMAGE_FRAME*/ colorFrame,
                [In] ref Matrix4 worldToCameraTransform);

            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            void CalculateMesh(
                [In] uint voxelStep,
                [Out, MarshalAs(UnmanagedType.Interface)] out INuiFusionColorMesh mesh);

            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            void ExportVolumeBlock(
                [In] uint sourceOriginX,
                [In] uint sourceOriginY,
                [In] uint sourceOriginZ,
                [In] uint destinationResolutionX,
                [In] uint destinationResolutionY,
                [In] uint destinationResolutionZ,
                [In] uint voxelStep,
                [In] uint cbVolumeBlock,
                [In] uint cbColorVolumeBlock,
                [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 7)] short[] volumeBlock,
                [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 8)] int[] colorVolumeBlock);

            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            void ImportVolumeBlock(
                [In] uint cbVolumeBlock,
                [In] uint cbColorVolumeBlock,
                [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] short[] volumeBlock,
                [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] int[] colorVolumeBlock);

            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            void DepthToDepthFloatFrame(
                [In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] UInt16[] depthImageData,
                [In] uint countDepthImageDataBytes,
                [In] ref NUI_FUSION_IMAGE_FRAME depthFloatFrame,
                [In] float minDepthClip,
                [In] float maxDepthClip,
                [In] bool mirrorDepth);


            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            void SmoothDepthFloatFrame(
                [In] ref NUI_FUSION_IMAGE_FRAME depthFloatFrame,
                [In] ref NUI_FUSION_IMAGE_FRAME smoothDepthFloatFrame,
                [In] uint kernelWidth,
                [In] float distanceThreshold);

            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            void AlignPointClouds(
                [In] ref NUI_FUSION_IMAGE_FRAME referencePointCloudFrame,
                [In] ref NUI_FUSION_IMAGE_FRAME observedPointCloudFrame,
                [In] ushort maxAlignIterationCount,
                [In] ref NUI_FUSION_IMAGE_FRAME deltaFromReferenceFrame,
                [Out] out float alignmentEnergy,
                [In, Out] ref Matrix4 referenceToObservedTransform);

            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            void SetAlignDepthFloatToReconstructionReferenceFrame(
                [In] ref NUI_FUSION_IMAGE_FRAME referenceDepthFloatFrame);

            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            void CalculatePointCloudAndDepth(
                [In] ref NUI_FUSION_IMAGE_FRAME pointCloudFrame,
                [In] ref NUI_FUSION_IMAGE_FRAME depthFloatFrame,
                [In] ref NUI_FUSION_IMAGE_FRAME colorFrame,
                [In] ref Matrix4 worldToCameraTransform);

        };

        [StructLayoutAttribute(LayoutKind.Sequential, Pack = 8)]
        public struct NUI_FUSION_CAMERA_POSE_FINDER_PARAMETERS
        {
            public uint featureSampleLocationsPerFrameCount;
            public uint maxPoseHistoryCount;
            public float maxDepthThreshold;
        };

        [Guid("42C1992C-043A-492D-A486-E9275197E7E6")]
        [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
        [ComImport()]
        public interface INuiFusionMatchCandidates
        {
            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            [PreserveSig]
            uint MatchPoseCount();

            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            void GetMatchPoses(
                [Out] out IntPtr /*Matrix4[]*/ poses);

            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            [PreserveSig]
            uint MatchSimilarityCount();

            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            void GetMatchSimilarities(
                [Out] out IntPtr /*float[]*/ similarityMeasurements);

            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            void CalculateMinimumDistance(
                [Out] out float minimumDistance);

        };

        [Guid("4C98136C-F201-4C00-9911-4FCB9918FFD5")]
        [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
        [ComImport()]
        public interface INuiFusionCameraPoseFinder
        {
            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            void ResetCameraPoseFinder();

            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            void ProcessFrame(
                [In] ref NUI_FUSION_IMAGE_FRAME depthFloatFrame,
                [In] ref NUI_FUSION_IMAGE_FRAME colorFrame,
                [In] ref Matrix4 worldToCameraTransform,
                [In] float minimumDistanceThreshold,
                [Out] out bool addedPose,
                [Out] out bool historyTrimmed);

            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            void FindCameraPose(
                [In] ref NUI_FUSION_IMAGE_FRAME depthFloatFrame,
                [In] ref NUI_FUSION_IMAGE_FRAME colorFrame,
                [Out, MarshalAs(UnmanagedType.Interface)] out INuiFusionMatchCandidates matchCandidates);

            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            void LoadCameraPoseFinderDatabase(
                [In, MarshalAs(UnmanagedType.BStr)] string filename);

            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            void SaveCameraPoseFinderDatabase(
                [In, MarshalAs(UnmanagedType.BStr)] string filename);

            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            void GetCameraPoseFinderParameters(
               [Out] out NUI_FUSION_CAMERA_POSE_FINDER_PARAMETERS cameraPoseFinderParameters);

            [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
            [PreserveSig]
            uint GetStoredPoseCount();

        };
    }
}
